﻿#region

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;

#endregion

namespace CuongHanh.Context
{
    public class JsonSerializer
    {
        public static string Serialize<T>(T obj,
                                          params string[] fieldNames)
        {
            if(fieldNames == null)
                return JsonConvert.SerializeObject(obj);
            return JsonConvert.SerializeObject(obj,
                                               Formatting.Indented,
                                               new JsonSerializerSettings
                                                   {
                                                           ContractResolver = new DynamicContractResolver(typeof(T), fieldNames)
                                                   });
        }

        public static string SerializeList<T>(IEnumerable<T> obj,
                                           params string[] fieldNames)
        {
            if(fieldNames == null)
                return JsonConvert.SerializeObject(obj);
            return JsonConvert.SerializeObject(obj,
                                               Formatting.Indented,
                                               new JsonSerializerSettings
                                                   {
                                                           ContractResolver = new DynamicContractResolver(typeof(T), fieldNames)
                                                   });
        }

        /// <summary>
        ///   Deserialize for object
        /// </summary>
        /// <typeparam name="T"> </typeparam>
        /// <param name="value"> </param>
        /// <returns> </returns>
        public static T Deserialize<T>(string value)
        {
            if(string.IsNullOrEmpty(value))
                return default(T);
            return JsonConvert.DeserializeObject<T>(value);
        }

        /// <summary>
        ///   Deseriallize for IEnumberable object
        /// </summary>
        /// <typeparam name="T"> </typeparam>
        /// <param name="value"> </param>
        /// <returns> </returns>
        public static List<T> DeserializeList<T>(string value)
        {
            if(string.IsNullOrEmpty(value))
                return null;
            List<T> objectType = new List<T>();
            return JsonConvert.DeserializeAnonymousType(value,
                                                        objectType);
        }
    }

    internal class DynamicContractResolver : DefaultContractResolver
    {
        private readonly Type _type;
        private readonly string[] _fieldNames;

        public DynamicContractResolver(Type type, string[] fieldNames)
        {
            _type = type;
            _fieldNames = fieldNames;
        }

        protected override IList<JsonProperty> CreateProperties(Type type,
                                                                MemberSerialization memberSerialization)
        {
            IList<JsonProperty> properties = base.CreateProperties(type,
                                                                   memberSerialization);
            if(_type == type && _fieldNames.Length > 0)
                properties = properties.Where(c => _fieldNames.Contains(c.PropertyName)).ToList();
            return properties;
        }
    }
}
